"""
默认配置文件
包含所有训练、数据、模型的默认参数
"""
import torch
from pathlib import Path


class DefaultConfig:
    """默认配置类"""
    
    # ======================== 模型配置 ========================
    model_type = 'baseline_cnn'  # 可选: 'baseline_cnn', 'deep_cnn', 'gcnet'
    num_images = 20              # 每个样本的图像数量
    num_features = 6             # 传统特征数量
    
    # ======================== 数据配置 ========================
    data_dir = '/root/workspace'
    image_size = (288, 96)       # (width, height)
    
    # CSV文件列表
    train_csv = [
        'train_dataset_大号瓶_converted.csv',
        'train_dataset_试剂瓶_converted.csv',
        'train_dataset_小号瓶_converted.csv'
    ]
    
    val_csv = [
        'test_dataset_大号瓶_converted.csv',
        'test_dataset_试剂瓶_converted.csv',
        'test_dataset_小号瓶_converted.csv'
    ]
    
    # 数据加载参数
    augment = False              # 是否进行数据增强
    num_workers = 8              # DataLoader工作进程数
    filter_negative = True       # 是否过滤负体积数据
    
    # ======================== 训练配置 ========================
    epochs = 200
    batch_size = 32
    learning_rate = 0.001
    optimizer = 'adam'           # 可选: 'adam', 'adamw', 'sgd'
    weight_decay = 0.0
    
    # ======================== 学习率调度器 ========================
    scheduler_type = 'plateau'   # 可选: 'plateau', 'cosine', None
    scheduler_mode = 'min'       # 'min' or 'max'
    scheduler_factor = 0.5       # 学习率衰减因子
    scheduler_patience = 5       # 等待epoch数
    scheduler_min_lr = 1e-6      # 最小学习率
    
    # ======================== 输出配置 ========================
    save_dir = 'results'
    experiment_name = 'baseline_cnn'
    save_period = 10             # 每隔多少epoch保存一次checkpoint
    print_freq = 200             # 每隔多少batch打印一次信息
    
    # ======================== 其他配置 ========================
    seed = 42
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    
    def __init__(self, **kwargs):
        """
        通过关键字参数更新配置
        
        用法:
            config = DefaultConfig(epochs=300, batch_size=64)
        """
        for key, value in kwargs.items():
            if hasattr(self, key):
                setattr(self, key, value)
            else:
                print(f"Warning: Unknown config parameter '{key}'")
    
    @property
    def results_dir(self):
        """结果保存目录"""
        return Path(self.save_dir) / self.experiment_name
    
    @property
    def model_save_path(self):
        """最佳模型保存路径"""
        return self.results_dir / f'{self.experiment_name}_best.pth'
    
    @property
    def log_file(self):
        """日志文件路径"""
        return self.results_dir / f'{self.experiment_name}_log.txt'
    
    @property
    def metrics_file(self):
        """指标文件路径"""
        return self.results_dir / f'{self.experiment_name}_metrics.csv'
    
    def update_from_dict(self, config_dict):
        """
        从字典更新配置
        
        参数:
            config_dict: 配置字典，可以是嵌套的
        """
        def _update_recursive(d, prefix=''):
            for key, value in d.items():
                if isinstance(value, dict):
                    _update_recursive(value, prefix)
                else:
                    # 尝试设置属性
                    attr_name = key
                    if hasattr(self, attr_name):
                        setattr(self, attr_name, value)
        
        _update_recursive(config_dict)
    
    def print_config(self):
        """打印当前配置"""
        print("\n" + "="*70)
        print("Configuration".center(70))
        print("="*70)
        
        print(f"\n【Model Configuration】")
        print(f"  Model Type: {self.model_type}")
        print(f"  Num Images: {self.num_images}")
        print(f"  Num Features: {self.num_features}")
        
        print(f"\n【Data Configuration】")
        print(f"  Data Directory: {self.data_dir}")
        print(f"  Image Size: {self.image_size}")
        print(f"  Batch Size: {self.batch_size}")
        print(f"  Num Workers: {self.num_workers}")
        print(f"  Augmentation: {self.augment}")
        print(f"  Filter Negative: {self.filter_negative}")
        
        print(f"\n【Training Configuration】")
        print(f"  Epochs: {self.epochs}")
        print(f"  Learning Rate: {self.learning_rate}")
        print(f"  Optimizer: {self.optimizer}")
        print(f"  Weight Decay: {self.weight_decay}")
        print(f"  Scheduler: {self.scheduler_type}")
        
        print(f"\n【Output Configuration】")
        print(f"  Save Directory: {self.results_dir}")
        print(f"  Experiment Name: {self.experiment_name}")
        print(f"  Save Period: {self.save_period}")
        
        print(f"\n【Device】")
        print(f"  Device: {self.device}")
        if torch.cuda.is_available():
            print(f"  GPU: {torch.cuda.get_device_name(0)}")
        
        print("="*70 + "\n")
    
    def to_dict(self):
        """将配置转换为字典"""
        config_dict = {}
        for key in dir(self):
            if not key.startswith('_') and not callable(getattr(self, key)):
                value = getattr(self, key)
                if not isinstance(value, Path):
                    config_dict[key] = value
        return config_dict


if __name__ == "__main__":
    # 测试配置
    config = DefaultConfig()
    config.print_config()
    
    # 测试更新配置
    config2 = DefaultConfig(epochs=300, batch_size=64)
    print("\nUpdated config:")
    print(f"  Epochs: {config2.epochs}")
    print(f"  Batch Size: {config2.batch_size}")